package cn.lhc.test.datasyn.common.aop;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.LongSerializationPolicy;
import com.google.gson.reflect.TypeToken;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;

/**
 * @ProjectName: acp
 * @Package: cn.lhc.test.datasyn.common.aop.AspectLog
 * @ClassName: AspectLog
 * @Author: lhc
 * @Description: 切面
 * @Date: 2019/7/31 上午 10:28
 */

@Aspect
@Component
@Slf4j
public class AspectLog {


    /**
     * 对存在注解 `ServiceLog`的方法做日志记录
     *
     * @param joinPoint  joinPoint
     * @param serviceLog serviceLog
     * @throws Throwable Throwable
     * @see ServiceLog
     */
//    @Around(value = "@annotation(ServiceLog)")
//    public Object logAroud(ProceedingJoinPoint joinPoint, ServiceLog serviceLog) throws Throwable {
//        return doAop(joinPoint);
//    }
    @Pointcut("execution(* cn.lhc.test.datasyn.controller.*.*(..))")
    public void exceptionAopPointCut() {
    }


    @Around(value = "exceptionAopPointCut()")
    public Object exceptionAop(ProceedingJoinPoint joinPoint) throws Throwable {
        return doAop(joinPoint);
    }

    public Object doAop(ProceedingJoinPoint joinPoint) throws Throwable {
        long beginTime = System.currentTimeMillis();
        Object result = joinPoint.proceed();
        long time = System.currentTimeMillis() - beginTime;
        String resultJson = new GsonBuilder()
                .serializeNulls()
                .setLongSerializationPolicy(LongSerializationPolicy.DEFAULT)
                .setDateFormat("yyyy-MM-dd hh:mm:ss")
                .create()
                .toJson(result);
        String className = joinPoint.getTarget().getClass().getSimpleName();
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        String methodName = methodSignature.getMethod().getName();
        // 参数名称
        String[] paramNames = methodSignature.getParameterNames();
        // 参数值
        Object[] params = joinPoint.getArgs();

        Map<String, Object> paramsJson = new HashMap<>(paramNames.length);
        for (int i = 0; i < paramNames.length; i++) {
            paramsJson.put(paramNames[i], params[i]);
        }
        Type type = new TypeToken<Map<String, Object>>() {
        }.getType();
        String paramsJsonString = new Gson().toJson(paramsJson, type);
        log.info("TargetClass:{}; method:{}; requestParams:{}; response:{}; time:{}ms", className, methodName, paramsJsonString, resultJson, time);
        return result;
    }
}
